#pragma once
#include <iostream>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/strand.hpp>
#include "ws_io_interface.h"

#define CONFIG_SUPPORT_WEBSOCKET_CLIENT
namespace wsx_
{
	namespace beast = boost::beast;         // from <boost/beast.hpp>
	namespace http = beast::http;           // from <boost/beast/http.hpp>
	namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
	namespace net = boost::asio;            // from <boost/asio.hpp>
	using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

	class Csession;

	class session : public std::enable_shared_from_this<session>
	{
		boost::beast::websocket::stream<beast::tcp_stream> ws_;
		boost::beast::flat_buffer rxBuffer_, txBuffer_;
		WsIoInterface* pp;
		
	public:
		// Take ownership of the socket
		explicit
			session(tcp::socket&& socket)
			: ws_(std::move(socket))
		{
			t1 = time(NULL);
		//	std::cout << "make session :" << socket.remote_endpoint().address() << std::endl;
		}

		void run(WsIoInterface* p);
		void on_run(void);
		void on_accept(boost::beast::error_code ec);
		void recvAsync(void);
		void sendAsync(std::string tmp);
		void do_RxTx(void);
		void on_read(boost::beast::error_code ec, std::size_t bytes_transferred);
		void on_write(boost::beast::error_code ec, std::size_t bytes_transferred);
		bool wbusy = false;
		bool session_valid = false;
		bool isFirst = false;
		time_t t1;
	};


	//client impliention
	class  ws_client
	{
	public:
		std::shared_ptr<session> session_sptr;
		std::shared_ptr<Csession> Csession_sptr;
		WsIoInterface io;

	};


	class Csession : public std::enable_shared_from_this<Csession>
	{
		tcp::resolver resolver_;
		websocket::stream<beast::tcp_stream> ws_;
		beast::flat_buffer rxBuffer_;
		WsIoInterface* pp;
		std::vector<ws_client*>* ws_clientVector;
	public:
		// Resolver and socket require an io_context
		explicit
			Csession(net::io_context& ioc)
			: resolver_(net::make_strand(ioc))
			, ws_(net::make_strand(ioc))
		{
		}

		// Start the asynchronous operation
		void
			run(std::vector<ws_client*>* vp,
				char const* host,
				char const* port);


		void
			on_resolve(
				beast::error_code ec,
				tcp::resolver::results_type results);

		void
			on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep);

		void
			on_handshake(beast::error_code ec);
		void recvAsync(void);
		void sendAsync(std::string tmp);
		void on_read(boost::beast::error_code ec, std::size_t bytes_transferred);
		void on_write(boost::beast::error_code ec, std::size_t bytes_transferred);
		void sendCheck(ws_client* c);
		void sendLanucher(ws_client* c);
		bool wbusy = false;
		bool session_valid = false;
		std::string host_;
		
		int port;
	};


	//export class ws_client;
	//notice




	//void bindApi(WsIoInterface* p);
}

void startServer(const char* addr,uint16_t port, bool isclient,std::vector<wsx_::ws_client*> *vp);